home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / COMMUNIC / 1572A.ZIP / KMT_IBM3.ZIP / MSSTER.ASM < prev    next >
Assembly Source File  |  1989-07-11  |  38KB  |  838 lines

  1.         NAME    msster
  2. ; File MSSTER.ASM
  3. ; Last edit 21 Jan 1988
  4. ; 11 Dec 1988 Version 2.32
  5. ; 1 July 1988 Version 2.31
  6. ; 12 June 1988 Add error recovery if serial port fails to initialize
  7. ; 29 May 1988 Cleanup one letter Connect dispatch routines
  8. ; 27 Feb 1988 Add capability of stdin being a file. [jrd]
  9. ; 27 Jan 1988 Remove serrst call, done now in mssker idle loop. [jrd]
  10. ; 1 Jan 1988 version 2.30
  11.  
  12.         public  clscpt, defkey, clscpi, ploghnd, sloghnd, tloghnd
  13.         public  dopar, shokey, cptchr, pktcpt, targ
  14.         public  kbdflg, shkadr, telnet, ttyact
  15.         public  cnvlin, katoi, decout, valout, atoi, cnvstr
  16.         include mssdef.h
  17.  
  18. braceop equ     7bh                     ; opening curly brace
  19. bracecl equ     7dh                     ; closing curly brace
  20.  
  21. datas   segment public 'datas'
  22.         extrn   flags:byte, trans:byte, buff:byte, portval:word
  23.  
  24. targ    termarg <0,1,80,24,cptchr,2dch,0,scntab,deftab,0,,parnon>
  25. crlf    db      cr,lf,'$'
  26. tmsg1   db      cr,lf,'(Connecting to host, type $'
  27. tmsg3   db      ' C to return to PC)',cr,lf,cr,lf,cr,lf,'$'
  28. erms25  db      cr,lf,'?Input must be numeric$'
  29. erms22  db      cr,lf,'?No open logging file$'
  30. erms23  db      cr,lf,'?Error writing session log, suspending capture.'
  31.         db      cr,lf,'$'
  32. erms24  db      cr,lf,'?Error writing Packet log$'
  33. esctl   db      'Control-$'
  34.  
  35. inthlp db cr,lf,'  ?  This message                    F  Dump screen to file'
  36.        db cr,lf,'  C  Close the connection            P  Push to DOS'
  37.        db cr,lf,'  S  Status of the connection        Q  Quit logging'
  38.        db cr,lf,'  M  Toggle mode line                R  Resume logging'
  39.        db cr,lf,'  B  Send a Break                    0  Send a null'
  40.        db cr,lf,'  L  Send a long 1.8 s Break         H  Hangup phone'
  41.        db cr,lf,'  Typing the escape character will send it to the host'
  42.        db 0               ; this short-form obscures less screen area [jrd]
  43.  
  44. intprm  db      'Command> $'
  45. intclet db      'B','C','F','H','L'     ; single letter commands
  46.         db      'M','P','Q','R','S'     ; must parallel dispatch table intcjmp
  47.         db      '?','0'
  48. numlet  equ     $ - intclet             ; number of entries
  49. intcjmp dw      intchb,intchc,intchf,intchh,intchl
  50.         dw      intchm,intchp,intchq,intchr,intchs
  51.         dw      intchu,intchn
  52.  
  53. pktbuf  db      cptsiz dup (?)  ; packet logging buffer
  54. pktbp   dw      pktbuf          ; buffer pointer to next free byte
  55. pktlft  dw      cptsiz          ; number free bytes left
  56. capbuf  db      cptsiz dup (?)  ; session logging buffer
  57. capbp   dw      capbuf          ; buffer pointer to next free byte
  58. caplft  dw      cptsiz          ; number free bytes left
  59.  
  60. ploghnd dw      -1              ; packet logging handle
  61. sloghnd dw      -1              ; session logging handle
  62. tloghnd dw      -1              ; transaction logging handle
  63.  
  64. clotab  db      4
  65.         mkeyw   'All',logpkt+logses+logtrn
  66.         mkeyw   'Packets',logpkt
  67.         mkeyw   'Session',logses
  68.         mkeyw   'Transaction',logtrn
  69.  
  70. clseslog db     cr,lf,' Closing Session log$'
  71. clpktlog db     cr,lf,' Closing Packet log$'
  72. cltrnlog db     cr,lf,' Closing Transaction log$'
  73. clohlp  db      cr,lf,' One of the following log files:'
  74.         db      cr,lf,' ALL, Packets, Session, Transaction$'
  75. scntab  dw      0
  76. deftab  dw      0
  77. sttmsg  db      cr,lf,'Type space to continue ...$'
  78. kbdflg  db      0                       ; non-zero means char here from Term
  79. ttyact  db      0                       ; Connect mode active, if non-zero
  80. shkadr  dw      0                       ; offset of replacement Show Key cmd
  81. ten     dw      10                      ; multiplier for setatoi
  82. nbase   dw      ?                       ; currently active number base
  83. numset  db      '0123456789ABCDEF'      ; number conversion alphabet
  84. tmp     db      ?
  85. datas   ends
  86.  
  87. code    segment public 'code'
  88.         extrn   comnd:near, outchr:near, stat0:near, iseof:near
  89.         extrn   clrbuf:near, term:near, strlen:near
  90.         extrn   prtchr:near, ihostr:near
  91.         extrn   beep:near, puthlp:near, getbaud:near, serhng:near
  92.         extrn   serini:near,serrst:near, sendbr:near, showkey:near
  93.         extrn   fpush:near, dumpscr:near, pcwait:near, sendbl:near
  94.         assume  cs:code, ds:datas
  95.  
  96. ; the show key command
  97. shokey  proc    near
  98.         cmp     shkadr,0                ; keyboard translator present?
  99.         je      shokey1                 ; e = no, use regular routines
  100.         mov     bx,shkadr               ; get offset of replacement routine
  101.         jmp     bx                      ; and execute it rather than us
  102. shokey1:jmp     rskp                    ; and return
  103. shokey  endp
  104. ; enter with ax/scan code to define, si/ pointer to definition, cx/ length
  105. ; of definition.  Defines it in definition table. Obsolete.
  106. defkey  proc    near
  107.         ret
  108. defkey  endp
  109.  
  110. ; This is the CONNECT command
  111.  
  112. TELNET  PROC    NEAR
  113.         mov     ah,cmcfm
  114.         call    comnd                   ; Get a confirm
  115.          jmp    r                       ;  Didn't get a confirm
  116.         mov     ah,prstr                ; Output
  117.         mov     dx,offset crlf          ; a crlf
  118.         int     dos
  119.         cmp     flags.vtflg,0           ; emulating a terminal?
  120.         jne     teln1                   ; ne= yes, skip flashing message
  121.         call    domsg                   ; Reassure user
  122. teln1:  call    serini                  ; ensure port is inited now
  123.         mov     al,0                    ; initial flags
  124.         mov     ttyact,1                ; say telnet is active
  125.         cmp     flags.modflg,0          ; mode line enabled?
  126.         jne     tel010                  ; ne = yes
  127.         or      al,modoff               ; no, make sure it stays off
  128.  
  129. tel010: or      al,havtt                ; defaults (!)
  130.         test    flags.debug,logses      ; debug mode?
  131.         jz      tel0                    ; z = no, keep going
  132.         or      al,trnctl               ; yes, show control chars
  133. tel0:   cmp     flags.vtflg,0           ; emulating a terminal?
  134.         je      tel1                    ; e = no
  135.         or      al,emheath              ; say emulating some kind of terminal
  136. tel1:   mov     bx,portval
  137.         cmp     [bx].ecoflg,0           ; echoing?
  138.         jz      tel2
  139.         or      al,lclecho
  140. tel2:   call    getbaud                 ; pickup current baud rate for port
  141.         mov     targ.flgs,al            ; store flags
  142.         mov     ah,flags.comflg         ; COMs port identifier
  143.         mov     targ.prt,ah             ; Port 1 or 2, etc
  144.         mov     ah,trans.escchr         ; escape character
  145.         mov     targ.escc,ah
  146.         mov     ah,[bx].parflg          ; parity flag
  147.         mov     targ.parity,ah
  148.         mov     ax,[bx].baud            ; baud rate identifier
  149.         mov     targ.baudb,al
  150.         xor     ah,ah
  151.         test    flags.capflg,logses     ; select session logging flag bit
  152.         jz      tel3                    ; z = no logging
  153.         mov     ah,capt                 ; set capture flag
  154. tel3:   or      targ.flgs,ah
  155.  
  156. TEM:    call    serini                  ; init serial port
  157.         jnc     tem0                    ; nc = success
  158.         mov     ttyact,0                ; say we are no longer active
  159.         jmp     rskp                    ; and exit Connect mode
  160.  
  161. tem0:   mov     dx,offset crlf          ; give user an indication that we are
  162.         mov     ah,prstr                ; entering terminal mode
  163.         int     dos
  164.         mov     ax,offset targ          ; Point to terminal arguments
  165.         call    term                    ; Call the main Terminal procedure
  166.         or      targ.flgs,scrsam        ; assume screen is the same
  167. tem1:   mov     al,kbdflg               ; get the char from Term, if any
  168.         mov     kbdflg,0                ; clear the flag
  169.         cmp     al,0                    ; was there a char from Term?
  170.         jne     intch2                  ; ne = yes, else ask for one from kbd
  171.  
  172. intchar:call    iseof                   ; stdin at eof?
  173.         jnc     intch1                  ; nc = not eof, get more
  174.         mov     al,'C'                  ; use C when file is empty
  175.         jmp     intchc                  ;  to provide an exit
  176. intch1: mov     ah,coninq               ; read keyboard, no echo
  177.         int     dos                     ; get a char
  178.         cmp     al,0                    ; scan code indicator?
  179.         jne     intch2                  ; ne = no, ascii
  180.         mov     ah,coninq               ; read and discard scan code
  181.         int     dos
  182.         jmp     short intch1            ; try again
  183. intch2: cmp     al,' '                  ; space?
  184.         je      tem                     ; e = yes, ignore it
  185.         cmp     al,cr                   ; check ^M (cr) against plain ascii M
  186.         je      tem                     ; exit on cr
  187.         cmp     al,trans.escchr         ; Is it the escape char?
  188.         jne     intch3                  ; ne = no
  189.         mov     ah,al
  190.         call    outchr
  191.          nop
  192.          nop
  193.          nop
  194.         jmp     tem                     ; Return, we are done here
  195. intch3: push    es
  196.         push    ds
  197.         pop     es
  198.         mov     di,offset intclet       ; command letters
  199.         mov     cx,numlet               ; quantity of them
  200.         cmp     al,' '                  ; control code?
  201.         jae     intch3a                 ; ae = no
  202.         or      al,40H                  ; convert control chars to printable
  203. intch3a:cmp     al,96                   ; lower case?
  204.         jb      intch3b                 ; b = no
  205.         and     al,not (20h)            ; move to upper case
  206. intch3b:cld
  207.         repne   scasb                   ; find the matching letter
  208.         pop     es
  209.         jne     intch4                  ; ne = not found, beep and get another
  210.         dec     di                      ; back up to letter
  211.         sub     di,offset intclet       ; get letter number
  212.         shl     di,1                    ; make it a word index
  213.         jmp     intcjmp[di]             ; dispatch to it
  214. intch4: call    beep                    ; say illegal character
  215.         jmp     intchar
  216.  
  217. intchb: call    sendbr                  ; 'B' send a break
  218.         jmp     tem                     ; And return
  219.  
  220. intchc: mov     ttyact,0                ; 'C' say we are no longer active
  221.         jmp     rskp                    ; and exit Connect mode
  222.  
  223. intchf: call    dumpscr                 ; 'F' dump screen, use msy routine
  224.         jmp     tem                     ; and return
  225.  
  226. intchh: call    serhng                  ; 'H' hangup phone
  227.         call    serrst                  ; turn off port
  228.         jmp     tem
  229.  
  230. intchl: call    sendbl                  ; 'L' send a long break
  231.         jmp     tem
  232.  
  233. intchm: cmp     flags.modflg,1          ; 'M' toggle mode line, enabled?
  234.         jne     intchma                 ; ne = no, leave it alone
  235.         xor     targ.flgs,modoff        ; enabled, toggle its state
  236. intchma:jmp     tem                     ; and reconnect
  237.  
  238. intchp: push    bx                      ; 'P' push to DOS
  239.         mov     bx,portval
  240.         mov     ah,byte ptr [bx].flowc  ; get XOFF char, or null
  241.         pop     bx
  242.         or      ah,ah                   ; check for null (no flow control)
  243.         jz      intchpa                 ; z = null, don't send one
  244.         call    outchr                  ; send XOFF to host while we are away
  245.          nop
  246.          nop
  247.          nop
  248. intchpa:call    serrst                  ; turn off serial interrupts
  249.         call    fpush                   ; try pushing
  250.          nop
  251.          nop
  252.          nop
  253.         mov     dx,offset sttmsg        ; say we have returned
  254.         mov     ah,prstr
  255.         int     dos
  256.         call    serini                  ; init serial port again
  257.         jc      intchc                  ; nc = failure
  258.         call    ihostr                  ; XON the host (if using flow control)
  259.         jmp     intchsb                 ; wait for a space
  260.  
  261. intchq: test    targ.flgs,capt          ; 'Q' suspend logging. Logging active?
  262.         jz      intchq1                 ; z = no
  263.         and     targ.flgs,not capt      ; stop capturing
  264. intchq1:jmp     tem                     ; and resume
  265.  
  266. intchr: test    flags.capflg,logses     ; 'R' resume logging. Can we capture?
  267.         jz      intchr1                 ; z = no
  268.         test    targ.flgs,capt          ; already capturing?
  269.         jnz     intchr1                 ; yes, can't toggle back on then
  270.         or      targ.flgs,capt          ; else turn flag on
  271. intchr1:jmp     tem                     ; and resume
  272.  
  273. intchs: call    stat0                   ; 'S' status, call stat0
  274.         call    puthlp                  ; put help on screen
  275.         mov     dx,offset sttmsg
  276.         mov     ah,prstr
  277.         int     dos
  278. intchsa:call    iseof                   ; is stdin at eof?
  279.         jnc     intchsb                 ; nc = not eof, get more
  280.         jmp     tem                     ; resume if EOF
  281. intchsb:mov     ah,coninq               ; console input, no echo
  282.         int     dos
  283.         cmp     al,' '                  ; space?
  284.         jne     intchsa
  285.         and     targ.flgs,not scrsam    ; remember screen changed
  286.         jmp     tem
  287.  
  288. intchu: mov     ax,offset inthlp        ; '?' get help message
  289.         call    puthlp                  ; write help msg
  290.         mov     dx,offset intprm
  291.         mov     ah,prstr                ; Print it
  292.         int     dos
  293.         and     targ.flgs,not scrsam    ; remember screen changed
  294.         jmp     intchar                 ; Get another char
  295.  
  296. intchn: mov     ah,0                    ; '0' send a null
  297.         call    outchr
  298.          nop
  299.          nop
  300.          nop
  301.         jmp     tem
  302. TELNET  ENDP
  303. ; Reassure user about connection to the host. Tell him what escape sequence
  304. ; to use to return and the communications port and baud; rate being used
  305.  
  306. DOMSG   PROC    NEAR
  307.         mov     ah,prstr
  308.         mov     dx,offset tmsg1
  309.         int     dos
  310.         call    escprt
  311.         mov     ah,prstr
  312.         mov     dx,offset tmsg3
  313.         int     dos
  314.         ret
  315. DOMSG   ENDP
  316.  
  317. ; print the escape character in readable format.
  318.  
  319. ESCPRT  PROC    NEAR
  320.         mov     dl,trans.escchr
  321.         cmp     dl,' '
  322.         jge     escpr2
  323.         push    dx
  324.         mov     ah,prstr
  325.         mov     dx,offset esctl
  326.         int     dos
  327.         pop     dx
  328.         add     dl,040H         ; Make it printable
  329. escpr2: mov     ah,conout
  330.         int     dos
  331.         ret
  332. ESCPRT  ENDP
  333.  
  334.  
  335. ; Set parity for character in Register AL
  336.  
  337. dopar:  push    bx
  338.         mov     bx,portval
  339.         mov     bl,[bx].parflg          ; get parity flag byte
  340.         cmp     bl,parnon               ; No parity?
  341.         je      parret                  ; Just return
  342.         and     al,07FH                 ; Strip parity. Same as Space parity
  343.         cmp     bl,parspc               ; Space parity?
  344.         je      parret                  ; e = yes, then we are done here
  345.         cmp     bl,parevn               ; Even parity?
  346.         jne     dopar0                  ; ne = no
  347.         or      al,al
  348.         jpe     parret                  ; pe = even parity now
  349.         xor     al,080H                 ; Make it even parity
  350.         jmp     short parret
  351. dopar0: cmp     bl,parmrk               ; Mark parity?
  352.         jne     dopar1                  ; ne = no
  353.         or      al,080H                 ; Turn on the parity bit
  354.         jmp     short parret
  355. dopar1: cmp     bl,parodd               ; Odd parity?
  356.         or      al,al
  357.         jpo     parret                  ; Already odd, leave it
  358.         xor     al,080H                 ; Make it odd parity
  359. parret: pop     bx
  360.         ret
  361.  
  362. cptchr  proc    near                    ; session capture routine, char in al
  363.         push    di
  364.         mov     di,capbp                ; buffer pointer
  365.         mov     byte ptr [di],al
  366.         inc     capbp
  367.         pop     di
  368.         dec     caplft                  ; decrement chars remaining
  369.         jg      cptch1                  ; more room, forget this part
  370.         call    cptdmp                  ; dump the info
  371. cptch1: ret
  372. cptchr  endp
  373.  
  374. cptdmp  proc    near                    ; empty the capture buffer
  375.         push    ax
  376.         push    bx
  377.         push    cx
  378.         push    dx
  379.         mov     bx,sloghnd              ; get file handle
  380.         cmp     bx,0                    ; is file open?
  381.         jle     cptdm1                  ; le = no, skip it
  382.         mov     cx,cptsiz               ; original buffer size
  383.         sub     cx,caplft               ; minus number remaining
  384.         jl      cptdm2                  ; means error
  385.         jcxz    cptdm1                  ; z = nothing to do
  386.         mov     dx,offset capbuf        ; the capture routine buffer
  387.         mov     ah,write2               ; write with filehandle
  388.         int     dos                     ; write out the block
  389.         jc      cptdm2                  ; carry set means error
  390.         mov     capbp,offset capbuf
  391.         mov     caplft,cptsiz           ; init buffer ptr & chrs left
  392.         jmp     short cptdm1
  393. cptdm2: and     targ.flgs,not capt      ; so please stop capturing
  394.         mov     dx,offset erms23        ; tell user the bad news
  395.         mov     ah,prstr
  396.         int     dos
  397. cptdm1: pop     dx
  398.         pop     cx
  399.         pop     bx
  400.         pop     ax
  401.         ret
  402. cptdmp  endp
  403.  
  404. pktcpt  proc    near                    ; packet log routine, char in al
  405.         push    di
  406.         mov     di,pktbp
  407.         mov     [di],al                 ; store char in buffer
  408.         inc     pktbp                   ; move pointer to next free byte
  409.         pop     di
  410.         dec     pktlft                  ; decrement chars remaining
  411.         jg      pktcp1                  ; more room, forget this part
  412.         call    pktdmp                  ; dump the info
  413. pktcp1: ret
  414. pktcpt  endp
  415.  
  416. pktdmp  proc    near                    ; empty the capture buffer
  417.         push    ax
  418.         push    bx
  419.         push    cx
  420.         push    dx
  421.         mov     bx,ploghnd              ; get file handle
  422.         cmp     bx,0                    ; is file open?
  423.         jle     cptdm1                  ; le = no, skip it
  424.         mov     cx,cptsiz               ; original buffer size
  425.         sub     cx,pktlft               ; minus number remaining
  426.         jl      pktdm2                  ; l means error
  427.         jcxz    pktdm1                  ; z = nothing to do
  428.         mov     dx,offset pktbuf        ; the capture routine buffer
  429.         mov     ah,write2               ; write with filehandle
  430.         int     dos                     ; write out the block
  431.         jc      pktdm2                  ; carry set means error
  432.         mov     pktbp,offset pktbuf
  433.         mov     pktlft,cptsiz           ; init buffer ptr & chrs left
  434.         jmp     short pktdm1
  435. pktdm2: and     targ.flgs,not capt      ; so please stop capturing
  436.         mov     dx,offset erms24        ; tell user the bad news
  437.         mov     ah,prstr
  438.         int     dos
  439.         call    clscp4                  ; close the packet log
  440. pktdm1: pop     dx
  441.         pop     cx
  442.         pop     bx
  443.         pop     ax
  444.         ret
  445. pktdmp  endp
  446.  
  447. ; CLOSE command
  448.  
  449. clscpt  proc    near
  450.         mov     ah,cmkey
  451.         mov     dx,offset clotab        ; close table
  452.         mov     bx,offset clohlp        ; help
  453.         call    comnd
  454.          jmp    r
  455.          nop
  456.         mov     tmp,bl
  457.         mov     ah,cmcfm
  458.         call    comnd
  459.          jmp    r
  460.         mov     bl,tmp
  461.         test    flags.capflg,0FFH       ; are any kinds active?
  462.         jz      clscp1                  ; z = no
  463.         cmp     bl,logpkt+logses+logtrn ; close all?
  464.         je      clscpi                  ; e = yes
  465.         cmp     bl,logpkt               ; just packet?
  466.         je      clscp4
  467.         cmp     bl,logses               ; just session?
  468.         je      clscp6
  469.         cmp     bl,logtrn               ; just session?
  470.         je      clscp8
  471. clscp1: mov     dx,offset erms22        ; say none active
  472.         mov     ah,prstr
  473.         int     dos
  474.         jmp     rskp
  475.                                         ; CLSCPI called at Kermit exit
  476. CLSCPI: call    clscp4                  ; close packet log
  477.         call    clscp6                  ; close session log
  478.         call    clscp8                  ; close transaction log
  479.         jmp     rskp                    ; return success
  480.  
  481. clscp4: push    bx                      ; PACKET LOG
  482.         mov     bx,ploghnd              ; packet log handle
  483.         cmp     bx,0                    ; is it open?
  484.         jle     clscp5                  ; e = no
  485.         call    pktdmp                  ; dump buffer
  486.         mov     ah,close2
  487.         int     dos
  488.         mov     ah,prstr
  489.         mov     dx,offset clpktlog      ; tell what we are doing
  490.         int     dos
  491. clscp5: mov     ploghnd,-1              ; say handle is invalid
  492.         pop     bx
  493.         and     flags.capflg,not logpkt ; say this log is closed
  494.         ret
  495.  
  496. clscp6: push    bx                      ; SESSION LOG
  497.         mov     bx,sloghnd              ; session log handle
  498.         cmp     bx,0                    ; is it open?
  499.         jle     clscp7                  ; e = no
  500.         call    cptdmp                  ; dump buffer
  501.         mov     ah,close2
  502.         int     dos
  503.         mov     ah,prstr
  504.         mov     dx,offset clseslog      ; tell what we are doing
  505.         int     dos
  506. clscp7: mov     sloghnd,-1              ; say handle is invalid
  507.         pop     bx
  508.         and     flags.capflg,not logses ; say this log is closed
  509.         ret
  510.  
  511. clscp8: push    bx                      ; TRANSACTION LOG
  512.         mov     bx,tloghnd              ; transaction log handle
  513.         cmp     bx,0                    ; is it open?
  514.         jle     clscp9                  ; e = no
  515.         mov     ah,close2
  516.         int     dos
  517.         mov     ah,prstr
  518.         mov     dx,offset cltrnlog      ; tell what we are doing
  519.         int     dos
  520. clscp9: mov     tloghnd,-1              ; say handle is invalid
  521.         pop     bx
  522.         and     flags.capflg,not logtrn ; say this log is closed
  523.         ret
  524. clscpt  endp
  525.  
  526. ; worker: copy line from si to di, first removing trailing spaces, second
  527. ; parsing out curly braced strings, then third converting \{b##} in strings
  528. ; to binary numbers. Returns carry set if error; else carry clear, with byte
  529. ; count in cx. Braces are optional but must occur in pairs.
  530. ; Items which cannot be converted to legal numbers are copied verbatium
  531. ; to the output string (ex: \{c}  is copied as \{c}  but \{x0d} is hex 0dh).
  532. cnvlin  proc    near
  533.         push    ax
  534.         push    si                      ; source ptr
  535.         push    di                      ; destination ptr
  536.         push    es                      ; end of save regs
  537.         push    ds                      ; move ds into es
  538.         pop     es                      ; use datas segment for es:di
  539.         call    cnvstr                  ; trim trailing, parse curly braces
  540.         xor     cx,cx                   ; initialize returned byte count
  541. cnvln1: cmp     byte ptr [si],0         ; at end of string?
  542.         je      cnvln2                  ; e = yes, exit
  543.         call    katoi                   ; read char, convert ascii to binary
  544.         cld
  545.         stosb                           ; save the char
  546.         inc     cx                      ; and count it
  547.         or      ah,ah                   ; is returned number > 255?
  548.         jz      cnvln1                  ; z = no, do more chars
  549.         push    ax
  550.         stosb                           ; save high order byte next
  551.         pop     ax
  552.         inc     cx
  553.         jmp     short cnvln1            ; do more chars
  554. cnvln2: mov     byte ptr [di],0         ; plant terminator
  555.         clc                             ; clear c bit, success
  556. cnvlnx: pop     es                      ; restore regs
  557.         pop     di                      ; destination ptr
  558.         pop     si                      ; source ptr
  559.         pop     ax
  560.         ret
  561. cnvlin  endp
  562.  
  563. ; Convert string by first remove trailing spaces and then removing surrounding
  564. ; curly brace delimiter pair. Converts text in place.
  565. ; Enter with source ptr in si.
  566. ; Preserves all registers, uses byte tmp. 9 Oct 1987 [jrd]
  567. ;
  568. cnvstr  proc    near
  569.         push    ax
  570.         push    cx
  571.         push    dx
  572.         push    si                      ; save start of source string
  573.         push    di
  574.         push    es
  575.                                         ; 1. Trim trailing spaces
  576.         mov     dx,si                   ; source address
  577.         call    strlen                  ; get current length to cx
  578.         jcxz    cnvst4                  ; z = nothing there
  579.         mov     di,si                   ; set di to source address
  580.         add     di,cx                   ; start at end of string
  581.         dec     di                      ; ignore terminator
  582.         mov     al,spc                  ; scan while spaces
  583.         push    ds
  584.         pop     es                      ; set es to datas segment
  585.         std                             ; search backward
  586.         repe    scasb                   ; scan off trailing spaces
  587.         mov     byte ptr [di+2],0       ; terminate string after last text
  588.         cld
  589.         mov     di,si                   ; set destination address to source
  590.                                         ; 2. Parse off curly brace delimiters
  591.         cmp     byte ptr [si],braceop   ; opening brace?
  592.         jne     cnvst4                  ; ne = no, ignore brace-matching code
  593.         inc     si                      ; skip opening brace
  594.         mov     dl,braceop              ; opening brace (we count them up)
  595.         mov     dh,bracecl              ; closing brace (we count them down)
  596.         mov     tmp,1                   ; we are at brace level 1
  597. cnvst1: cld                             ; search forward
  598.         lodsb                           ; read a string char
  599.         stosb                           ; store char (skips opening brace)
  600.         cmp     al,0                    ; at end of string?
  601.         je      cnvst4                  ; e = yes, we are done
  602.         cmp     al,dl                   ; an opening brace?
  603.         jne     cnvst2                  ; ne = no
  604.         inc     tmp                     ; yes, increment brace level
  605.         jmp     short cnvst1            ;  and continue scanning
  606.  
  607. cnvst2: cmp     al,dh                   ; closing brace?
  608.         jne     cnvst1                  ; ne = no, continue scanning
  609.         dec     tmp                     ; yes, decrement brace level
  610.         cmp     byte ptr [si],0         ; have we just read the last char?
  611.         jne     cnvst3                  ; no, continue scanning
  612.         mov     tmp,0                   ; yes, this is the closing brace
  613. cnvst3: cmp     tmp,0                   ; at level 0?
  614.         jne     cnvst1                  ; ne = no, #opening > #closing braces
  615.         mov     byte ptr [di-1],0       ; plant terminator on closing brace
  616.  
  617. cnvst4: pop     es                      ; recover original registers
  618.         pop     di
  619.         pop     si
  620.         pop     dx
  621.         pop     cx
  622.         pop     ax
  623.         ret
  624. cnvstr  endp
  625.  
  626. ; Convert ascii strings of the form "\{bnnn}" to a binary word in ax.
  627. ; The braces are optional but must occur in pairs. Numeric base indicator "b"
  628. ; is O or o or X or x or D or d or missing, for octal, hex, or decimal (def).
  629. ; Enter with si pointing at "\".
  630. ; Returns binary value in ax with carry clear and si to right of "}" or at
  631. ; terminating non-numeric char if successful; otherwise, a failure,
  632. ; return carry set with si = entry value + 1 and first read char in al.
  633.  
  634. katoi   proc    near
  635.         cld
  636.         lodsb                           ; get first char
  637.         xor     ah,ah                   ; clear high order field
  638.         push    cx                      ; save working reg
  639.         push    si                      ; save entry si+1
  640.         push    bx
  641.         push    ax                      ; save read char
  642. KATOI1: cmp     al,0                    ; end of text? ENTRY POINT FOR ATOI
  643.         je      katoi1a                 ; e = yes, exit failure
  644.         cmp     al,'\'                  ; escape char?
  645.         je      katoi1b                 ; e = yes
  646. katoi1a:jmp     katoix                  ; common jump point to exit failure
  647. katoi1b:lodsb                           ; get next char, maybe brace
  648.         cmp     al,0                    ; premature end?
  649.         je      katoi1a                 ; e = yes, exit failure
  650.         xor     bx,bx                   ; no conv yet, assume no opening brace
  651.         cmp     al,braceop              ; opening brace?
  652.         jne     katoi2                  ; ne = no, have number or base
  653.         mov     bl,bracecl              ; remember a closing brace is needed
  654.         lodsb                           ; get number base, if any
  655. katoi2: xor     cx,cx                   ; temporary place for binary value
  656.         mov     nbase,10                ; assume decimal numbers
  657.         cmp     al,0                    ; premature end?
  658.         je      katoix                  ; e = yes, exit failure
  659.         cmp     al,'a'                  ; lower case?
  660.         jb      katoi3                  ; b = no
  661.         cmp     al,'z'                  ; in range of lower case?
  662.         ja      katoi3                  ; a = no
  663.         and     al,5fh                  ; map to upper case
  664. katoi3: cmp     al,'O'                  ; octal?
  665.         jne     katoi4                  ; ne = no
  666.         mov     nbase,8                 ; set number base
  667.         jmp     short katoi6
  668. katoi4: cmp     al,'X'                  ; hex?
  669.         jne     katoi5                  ; ne = no
  670.         mov     nbase,16
  671.         jmp     short katoi6
  672. katoi5: cmp     al,'D'                  ; decimal?
  673.         jne     katoi7                  ; ne = no base char, assume decimal
  674.         mov     nbase,10
  675. katoi6: lodsb                           ; get a digit
  676. katoi7: cmp     al,0                    ; premature end?
  677.         je      katoi8a                 ; e = yes, use it as a normal end
  678.         cmp     al,bl                   ; closing brace?
  679.         je      katoi9                  ; e = yes
  680.         call    cnvdig                  ; convert ascii to binary digit
  681.         jc      katoi8                  ; c = cannot convert
  682.         inc     bh                      ; say we did a successful conversion
  683.         xor     ah,ah                   ; clear high order value
  684.         push    ax                      ; save this byte's value
  685.         xchg    ax,cx                   ; put binary summation in ax
  686.         mul     nbase                   ; scale up current sum
  687.         xchg    ax,cx                   ; put binary back in cx
  688.         pop     ax                      ; recover binary digit
  689.         add     cx,ax                   ; form running sum
  690.         jc      katoix                  ; c = overflow error, exit
  691.         cmp     dx,0                    ; overflow?
  692.         jne     katoix                  ; ne = yes, exit with error
  693.         jmp     short katoi6            ; get more
  694.  
  695. katoi8: cmp     bl,0                    ; closing brace needed?
  696.         jne     katoix                  ; ne = yes, but not found
  697. katoi8a:dec     si                      ; backup to reread terminator
  698. katoi9: cmp     bh,0                    ; did we do any conversion?
  699.         je      katoix                  ; e = no, exit failure
  700.         pop     ax                      ; throw away old saved ax
  701.         pop     bx                      ; restore bx
  702.         pop     ax                      ; throw away starting si, keep current
  703.         mov     ax,cx                   ; return final value in ax
  704.         pop     cx                      ; restore old cx
  705.         clc                             ; clear carry for success
  706.         ret
  707. katoix: pop     ax                      ; restore first read al
  708.         pop     bx
  709.         pop     si                      ; restore start value + 1
  710.         pop     cx                      ; restore old cx
  711.         stc                             ; set carry for failure
  712.         ret
  713. katoi   endp
  714.  
  715. cnvdig  proc    near                    ; convert ascii code in al to binary
  716.         push    cx                      ; return carry set if cannot
  717.         push    es                      ; nbase has numeric base
  718.         push    di
  719.         push    ax
  720.         cmp     al,'a'                  ; lower case?
  721.         jb      cnvdig1                 ; b = no
  722.         cmp     al,'f'                  ; highest hex digit
  723.         ja      cnvdigx                 ; a = illegal symbol
  724.         sub     al,'a'-'A'              ; convert 'a' to 'f' to upper case
  725. cnvdig1:mov     di,offset numset        ; set of legal number symbols
  726.         mov     cx,nbase                ; number of legal symbols in this base
  727.         cmp     cx,cx                   ; preset z flag
  728.         push    ds
  729.         pop     es                      ; point es at data segment
  730.         cld                             ; scan forward
  731.         repne   scasb                   ; find character in set
  732.         jne     cnvdigx                 ; ne = not found
  733. cnvdig2:inc     cx                      ; offset auto-dec of repne scasb above
  734.         sub     cx,nbase                ; counted off minus length
  735.         neg     cx                      ; two's complement = final value
  736.         pop     ax                      ; saved ax
  737.         mov     ax,cx                   ; return binary in al
  738.         clc                             ; c clear for success
  739.         jmp     short cnvdixx           ; exit
  740. cnvdigx:stc                             ; c set for failure
  741.         pop     ax
  742. cnvdixx:pop     di
  743.         pop     es
  744.         pop     cx
  745.         ret
  746. cnvdig  endp
  747.  
  748. decout  proc    near            ; display decimal number in ax
  749.         push    ax
  750.         push    cx
  751.         push    dx
  752.         mov     cx,10           ; set the numeric base
  753.         call    valout          ; convert and output value
  754.         pop     dx
  755.         pop     cx
  756.         pop     ax
  757.         ret
  758. decout  endp
  759.  
  760. valout  proc    near            ; output number in ax using base in cx
  761.                                 ; corrupts ax and dx
  762.         xor     dx,dx           ; clear high word of numerator
  763.         div     cx              ; (ax / cx), remainder = dx, quotient = ax
  764.         push    dx              ; save remainder for outputting later
  765.         or      ax,ax           ; any quotient left?
  766.         jz      valout1         ; z = no
  767.         call    valout          ; yes, recurse
  768. valout1:pop     dx              ; get remainder
  769.         add     dl,'0'          ; make digit printable
  770.         cmp     dl,'9'          ; above 9?
  771.         jbe     valout2         ; be = no
  772.         add     dl,'A'-1-'9'    ; use 'A'--'F' for values above 9
  773. valout2:mov     ah,conout
  774.         int     dos
  775.         ret
  776. valout  endp
  777.  
  778. ; Convert input in buffer pointed to by SI to real number which is returned
  779. ; in AX.  Enter with string size in AH.
  780. ; Return on failure, return skip on success.      Revised by [jrd]
  781. ATOI    PROC    NEAR
  782.         mov     bx,0            ; high order of this stays 0
  783.         mov     tmp,0           ; No input yet
  784.         mov     cl,ah           ; Number of chars of input
  785.         mov     ch,0            ; size of string
  786.         mov     ax,0            ; init sum
  787.         cld
  788. atoi0:  jcxz    atoi4           ; Fail on no input
  789.         lodsb                   ; get an input char
  790.         dec     cx              ; count number remaining
  791.         cmp     al,' '          ; leading space?
  792.         je      atoi0           ; e = yes, skip it
  793.         cmp     al,','          ; comma separator?
  794.         je      atoi0           ; e = yes, skip it
  795.         dec     si              ; back up source pointer for reread below
  796.         inc     cx              ; and readjust byte counter
  797.         mov     ax,0            ; clear sum
  798. atoi1:  push    ax              ; save sum
  799.         lodsb                   ; read a byte into al
  800.         mov     bl,al           ; put it into bl
  801.         pop     ax              ; regain sum
  802.         cmp     bl,'9'          ; check range for '0' to '9'
  803.         ja      atoi2           ; above '9'
  804.         cmp     bl,'0'
  805.         jb      atoi2           ; below '0'
  806.         sub     bl,'0'          ; take away ascii bias
  807.         mul     ten             ; sum * 10. dx = high, ax = low
  808.         add     ax,bx           ; add current value
  809.         mov     tmp,1           ; say have sum being computed
  810.         loop    atoi1
  811.         inc     si              ; inc for dec below
  812. atoi2:  dec     si              ; point at terminator
  813.         cmp     tmp,0           ; were any digits discovered?
  814.         je      atoi4           ; e = no, fail
  815. atoi3:  jmp     rskp            ; success exit, sum is in ax
  816. atoi4:  mov     dx,offset erms25 ; Input must be numeric
  817.         ret
  818. ATOI    ENDP
  819.  
  820. ; Jumping to this location is like retskp.  It assumes the instruction
  821. ;   after the call is a jmp addr.
  822.  
  823. RSKP    PROC    NEAR
  824.         pop     bp
  825.         add     bp,3
  826.         push    bp
  827.         ret
  828. RSKP    ENDP
  829.  
  830. ; Jumping here is the same as a ret
  831.  
  832. R       PROC    NEAR
  833.         ret
  834. R       ENDP
  835.  
  836. code    ends
  837.         end
  838.